package org.elastic.compreplatform.redis.core.factory;

import org.elastic.compreplatform.common.util.SpringConfigurerUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.exceptions.JedisConnectionException;

/**
 * ClassName: JedisConnectionFactory 
 * @Description: 构建redis连接工厂
 * @author JornTang
 * @date 2018年2月28日
 */
public class JedisConnectionFactory {
	private static Logger log = LoggerFactory.getLogger(JedisConnectionFactory.class);
	private JedisConnectionFactory() {}
	//jedis连接池配置
	private static JedisPoolConfig poolConfig = null;
	
	//jedis连接池
	private static JedisPool jedisPool = null;
	static {
		init();
	}
	//初始化
	public static void init() {
		buildJedisPoolConfig();
		buildJedisPool();
	}
	/**
	 * @Description: 初始连接池配置
	 * @return void  
	 * @throws
	 * @author JornTang
	 * @date 2018年2月28日
	 */
	private static void buildJedisPoolConfig() {
		if(poolConfig == null) {
			poolConfig = new JedisPoolConfig();
			
			//连接超时时是否阻塞，false时报异常,ture阻塞直到超时, 默认true
            poolConfig.setBlockWhenExhausted(true);
            
            //最大空闲连接数, 默认10个
            poolConfig.setMaxIdle(10);

            //最大连接数, 默认10个
            poolConfig.setMaxTotal(10);

            //获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,  默认-1
            poolConfig.setMaxWaitMillis(-1);

            //逐出连接的最小空闲时间 默认5000毫秒(5秒)
            poolConfig.setMinEvictableIdleTimeMillis(Long.valueOf(SpringConfigurerUtil.getProperty("redis.minEvictableIdleTimeMillis")));

            //最小空闲连接数, 默认0
            poolConfig.setMinIdle(3);

            //每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3
            poolConfig.setNumTestsPerEvictionRun(3);

            //对象空闲多久后逐出, 当空闲时间>该值 且 空闲连接>最大空闲数 时直接逐出,不再根据MinEvictableIdleTimeMillis判断  (默认逐出策略)   
            poolConfig.setSoftMinEvictableIdleTimeMillis(10000);

            // 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,
            // 默认-1
            poolConfig.setMaxWaitMillis(Long.valueOf(SpringConfigurerUtil.getProperty("redis.maxWaitMillis")));

            //对拿到的connection进行validateObject校验
            poolConfig.setTestOnBorrow(true);

            //在进行returnObject对返回的connection进行validateObject校验
            poolConfig.setTestOnReturn(true);

            //定时对线程池中空闲的链接进行validateObject校验
            poolConfig.setTestWhileIdle(true);
		}
	}
	/**
	 * @Description: 获取jedis实例
	 * @return   
	 * @return Jedis  
	 * @throws
	 * @author JornTang
	 * @date 2018年3月10日
	 */
	public static Jedis getJedis() {
		Jedis jedis = null;
		if(jedisPool == null) {
			buildJedisPool();
		}
		try {
            jedis = jedisPool.getResource();
        } catch (JedisConnectionException e) {
        	log.error("Could not get a resource from the pool.系统将无法正常使用。请检查你的redis服务");
        	throw new JedisConnectionException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
		return jedis;
	}
	/**
	 * @Description: 初始化连接池   
	 * @return void  
	 * @throws
	 * @author JornTang
	 * @date 2018年2月28日
	 */
	private static void buildJedisPool() {
		jedisPool = new JedisPool(poolConfig, SpringConfigurerUtil.getProperty("redis.host"), Integer.valueOf(SpringConfigurerUtil.getProperty("redis.port")));
	}
	/**
	 * @Description: 重载连接池
	 * @return   
	 * @return JedisPool  
	 * @throws
	 * @author JornTang
	 * @date 2018年2月28日
	 */
	public static JedisPool buildJedisPool(JedisPoolConfig poolConfig, String host, int port, int timeout, String password, int database) {
		return new JedisPool(poolConfig, host, port, timeout, password, database);
	}
	/**
	 * @Description: 重载连接池
	 * @return   
	 * @return JedisPool  
	 * @throws
	 * @author JornTang
	 * @date 2018年2月28日
	 */
	public static JedisPool buildJedisPool(JedisPoolConfig poolConfig, String host, int port, int timeout, String password) {
		return new JedisPool(poolConfig, host, port, timeout, password);
	}
	/**
	 * @Description: 重载连接池
	 * @return   
	 * @return JedisPool  
	 * @throws
	 * @author JornTang
	 * @date 2018年2月28日
	 */
	public static JedisPool buildJedisPool(String host, Integer port, Integer timeout, String password) {
		return new JedisPool(poolConfig, host, port, timeout, password);
	}
	/**
	 * @Description: 重载连接池
	 * @return   
	 * @return JedisPool  
	 * @throws
	 * @author JornTang
	 * @date 2018年2月28日
	 */
	public static JedisPool buildJedisPool(String host, Integer port, Integer timeout) {
		return new JedisPool(poolConfig, host, port, timeout);
	}
	/**
	 * @Description: 重载连接池
	 * @return   
	 * @return JedisPool  
	 * @throws
	 * @author JornTang
	 * @date 2018年2月28日
	 */
	public static JedisPool buildJedisPool(String host, Integer port) {
		return new JedisPool(poolConfig, host, port);
	}
}
